#include "Thread_Wrapper.h"

Thread_Wrapper::Thread_Wrapper() {
   currentState = THREAD_IDLE;
};


bool Thread_Wrapper::operator==(const Thread_Wrapper& obj) const {
   return (pthread_equal(threadID, threadID) != 0);
};


bool Thread_Wrapper::operator!=(const Thread_Wrapper& obj) const {
   return !operator==(obj);
};


void Thread_Wrapper::run() {
    setThreadState(THREAD_RUNNING);
    execute();
    setThreadState(THREAD_DEAD);
};

void* Thread_Wrapper::threadFunction(void* pt) {
    Thread_Wrapper* thrd = reinterpret_cast<Thread_Wrapper*>(pt);
    if (thrd) {
        thrd->run();
    }
    return NULL;
};


bool Thread_Wrapper::start(bool thread_join) {
    int result = pthread_create(&threadID,NULL,&(Thread_Wrapper::threadFunction),this);

    if (result == 0) {
        if (!thread_join) {
            pthread_detach(threadID);
        }
      return true;
    }
    else {
        setThreadState(THREAD_DEAD);
        cerr << "POSIXThread::start() - Failed to create thread." << threadID << endl;
        return false;
    }
};


int Thread_Wrapper::self() {
    return (int)threadID;
}


void Thread_Wrapper::detach(void) {
    if (pthread_detach(threadID) != 0) {
        cerr << "POSIXThread::detach() - Failed to detach thread." << threadID << endl;
    }
};


int Thread_Wrapper::join(void) {
    int status = 0;
    if (pthread_join(threadID, (void**)&status) != 0) {
        cerr << "POSIXThread::join() - Failed to join thread." << threadID << endl;
    }
    return status;
};


bool Thread_Wrapper::setPriority(int priority) {
    if ((priority > 10) || (priority < 0)) return false;

    struct sched_param threadParameter;

    threadParameter.sched_priority = priority;

    if (pthread_setschedparam(threadID, SCHED_OTHER, &threadParameter) != 0) {
        cerr << "POSIXThread::setPriority() - Failed to set thread priority." << threadID << endl;
        return false;
    }
    else {
        return true;
    }
};


int Thread_Wrapper::getPriority() {
    struct sched_param threadParameter;
    int    policy = 0;

    if(pthread_getschedparam(threadID, &policy, &threadParameter) == 0) {
        cerr << "POSIXThread::getPriority() - Failed to get thread priority." << threadID << endl;
        return -1;
    }
    else {
        return threadParameter.sched_priority;
    }
};


void  Thread_Wrapper::yield(void) const {
    sched_yield();
};


void Thread_Wrapper::terminate() {
    cout << "POSIXThread::terminate() - CANCEL INVOKED." << endl;

    if (pthread_cancel(threadID) != 0) {
        cerr << "POSIXThread::terminate() - Failed to cancel thread." << threadID;
    }
};


void Thread_Wrapper::exit() {
    pthread_exit((void**)0);
};


bool Thread_Wrapper::setThreadState(int state) {
    currentState = state;
    return true;
};


int Thread_Wrapper::getThreadState() {
    int state = currentState;
    return state;
};
